package rediscli

import (
	"context"
	"time"

	"github.com/go-redis/redis/v8"
)

func GetKeysWithPrefix(ctx context.Context, client *redis.Client, prefix string) ([]string, error) {
	var keys []string
	var cursor uint64
	for {
		// Use the SCAN command to retrieve all keys with the specified prefix
		keysList, nextCursor, err := client.Scan(ctx, cursor, prefix+"*", 1000000).Result()
		if err != nil {
			return nil, err
		}
		keys = append(keys, keysList...)
		cursor = nextCursor
		if cursor == 0 {
			break
		}
	}
	return keys, nil
}

func GetKey(ctx context.Context, client *redis.Client, key string) (string, error) {
	// Get the value of the key
	val, err := client.Get(ctx, key).Result()
	if err != nil {
		return "", err
	}

	return val, nil
}

func AcquireLock(ctx context.Context, client *redis.Client, key string, timeout time.Duration) (bool, error) {
	// SetNX sets the value of the key only if the key does not already exist.
	acquired, err := client.SetNX(ctx, key, true, timeout).Result()
	if err != nil {
		return false, err
	}
	return acquired, nil
}

func ReleaseLock(ctx context.Context, client *redis.Client, key string) error {
	_, err := client.Del(ctx, key).Result()
	return err
}

// delete prefix key
func DelKeysWithPrefix(ctx context.Context, client *redis.Client, prefix string) error {
	var cursor uint64
	for {
		// Use the SCAN command to retrieve all keys with the specified prefix
		keysList, nextCursor, err := client.Scan(ctx, cursor, prefix+"*", 1000000).Result()
		if err != nil {
			return err
		}
		for _, key := range keysList {
			if err := DelRedisKey(ctx, client, key); err != nil {
				return err
			}
		}
		cursor = nextCursor
		if cursor == 0 {
			break
		}
	}
	return nil
}

func JointRedisKey(key []string) (redisKey string) {
	for _, v := range key {
		redisKey = redisKey + v + ":"
	}
	return redisKey
}

func DelRedisKey(ctx context.Context, client *redis.Client, key string) error {
	_, err := client.Del(ctx, key).Result()
	return err
}

func SaveRedisKey(ctx context.Context, client *redis.Client, key string, value string) error {
	return client.Set(ctx, key, value, 0).Err()
}

func BgSaveRedisKey(ctx context.Context, client *redis.Client, key string, value string) error {
	return client.BgSave(ctx).Err()
}

func SaveRedisKeyWithExpire(ctx context.Context, client *redis.Client, key string, value string, expire time.Duration) error {
	return client.Set(ctx, key, value, expire).Err()
}
